package qos

import (
	"encoding/binary"
	"fmt"
	"time"
)

// QoS策略配置
type QoSProfile struct {
	Reliability ReliabilityQosPolicy
	Durability  DurabilityQosPolicy
	Deadline    DeadlineQosPolicy
	Liveliness  LivelinessQosPolicy
	History     HistoryQosPolicy
}

// 可靠性策略
type ReliabilityQosPolicy struct {
	Kind            ReliabilityKind
	MaxBlockingTime time.Duration
}

type ReliabilityKind int

const (
	BestEffortReliability ReliabilityKind = iota
	ReliableReliability
)

// 持久性策略
type DurabilityQosPolicy struct {
	Kind DurabilityKind
}

type DurabilityKind int

const (
	VolatileDurability DurabilityKind = iota
	TransientLocalDurability
	TransientDurability
	PersistentDurability
)

// 截止时间策略
type DeadlineQosPolicy struct {
	Period time.Duration
}

// 活跃度策略
type LivelinessQosPolicy struct {
	Kind          LivelinessKind
	LeaseDuration time.Duration
}

type LivelinessKind int

const (
	AutomaticLiveliness LivelinessKind = iota
	ManualByParticipantLiveliness
	ManualByTopicLiveliness
)

// 历史策略
type HistoryQosPolicy struct {
	Kind  HistoryKind
	Depth int
}

type HistoryKind int

const (
	KeepLastHistory HistoryKind = iota
	KeepAllHistory
)

// 默认QoS配置
func DefaultQoS() QoSProfile {
	return QoSProfile{
		Reliability: ReliabilityQosPolicy{
			Kind:            BestEffortReliability,
			MaxBlockingTime: 100 * time.Millisecond,
		},
		Durability: DurabilityQosPolicy{
			Kind: VolatileDurability,
		},
		Deadline: DeadlineQosPolicy{
			Period: time.Duration(0), // 无截止时间
		},
		Liveliness: LivelinessQosPolicy{
			Kind:          AutomaticLiveliness,
			LeaseDuration: 10 * time.Second,
		},
		History: HistoryQosPolicy{
			Kind:  KeepLastHistory,
			Depth: 1,
		},
	}
}

// 可靠QoS配置
func ReliableQoS() QoSProfile {
	return QoSProfile{
		Reliability: ReliabilityQosPolicy{
			Kind:            ReliableReliability,
			MaxBlockingTime: 100 * time.Millisecond,
		},
		Durability: DurabilityQosPolicy{
			Kind: TransientLocalDurability,
		},
		Deadline: DeadlineQosPolicy{
			Period: time.Duration(0),
		},
		Liveliness: LivelinessQosPolicy{
			Kind:          AutomaticLiveliness,
			LeaseDuration: 10 * time.Second,
		},
		History: HistoryQosPolicy{
			Kind:  KeepLastHistory,
			Depth: 10,
		},
	}
}

// 持久化QoS配置
func PersistentQoS() QoSProfile {
	return QoSProfile{
		Reliability: ReliabilityQosPolicy{
			Kind:            ReliableReliability,
			MaxBlockingTime: 100 * time.Millisecond,
		},
		Durability: DurabilityQosPolicy{
			Kind: PersistentDurability,
		},
		Deadline: DeadlineQosPolicy{
			Period: time.Duration(0),
		},
		Liveliness: LivelinessQosPolicy{
			Kind:          AutomaticLiveliness,
			LeaseDuration: 10 * time.Second,
		},
		History: HistoryQosPolicy{
			Kind:  KeepAllHistory,
			Depth: 0, // 无限深度
		},
	}
}

// 实时QoS配置
func RealTimeQoS() QoSProfile {
	return QoSProfile{
		Reliability: ReliabilityQosPolicy{
			Kind:            BestEffortReliability,
			MaxBlockingTime: 10 * time.Millisecond,
		},
		Durability: DurabilityQosPolicy{
			Kind: VolatileDurability,
		},
		Deadline: DeadlineQosPolicy{
			Period: 100 * time.Millisecond,
		},
		Liveliness: LivelinessQosPolicy{
			Kind:          ManualByTopicLiveliness,
			LeaseDuration: 5 * time.Second,
		},
		History: HistoryQosPolicy{
			Kind:  KeepLastHistory,
			Depth: 1,
		},
	}
}

// 检查QoS兼容性
func (qos *QoSProfile) IsCompatibleWith(other QoSProfile) bool {
	// 检查可靠性兼容性
	if qos.Reliability.Kind == ReliableReliability &&
		other.Reliability.Kind == BestEffortReliability {
		return false
	}

	// 检查持久性兼容性
	if qos.Durability.Kind > other.Durability.Kind {
		return false
	}

	// 检查截止时间兼容性
	if qos.Deadline.Period > 0 && other.Deadline.Period > 0 {
		if qos.Deadline.Period < other.Deadline.Period {
			return false
		}
	}

	// 检查活跃度兼容性
	if qos.Liveliness.Kind > other.Liveliness.Kind {
		return false
	}

	// 检查租约持续时间兼容性
	if qos.Liveliness.LeaseDuration < other.Liveliness.LeaseDuration {
		return false
	}

	return true
}

// 验证QoS配置
func (qos *QoSProfile) Validate() error {
	// 验证可靠性配置
	if qos.Reliability.Kind < BestEffortReliability ||
		qos.Reliability.Kind > ReliableReliability {
		return fmt.Errorf("invalid reliability kind")
	}

	// 验证持久性配置
	if qos.Durability.Kind < VolatileDurability ||
		qos.Durability.Kind > PersistentDurability {
		return fmt.Errorf("invalid durability kind")
	}

	// 验证历史配置
	if qos.History.Kind < KeepLastHistory ||
		qos.History.Kind > KeepAllHistory {
		return fmt.Errorf("invalid history kind")
	}

	if qos.History.Kind == KeepLastHistory && qos.History.Depth <= 0 {
		return fmt.Errorf("invalid history depth for KeepLast policy")
	}

	// 验证活跃度配置
	if qos.Liveliness.Kind < AutomaticLiveliness ||
		qos.Liveliness.Kind > ManualByTopicLiveliness {
		return fmt.Errorf("invalid liveliness kind")
	}

	if qos.Liveliness.LeaseDuration <= 0 {
		return fmt.Errorf("invalid lease duration")
	}

	return nil
}

// QoS策略序列化
func (qos *QoSProfile) Serialize() []byte {
	data := make([]byte, 32) // 固定大小

	// 序列化各个策略
	data[0] = byte(qos.Reliability.Kind)
	binary.BigEndian.PutUint64(data[1:9], uint64(qos.Reliability.MaxBlockingTime))

	data[9] = byte(qos.Durability.Kind)

	binary.BigEndian.PutUint64(data[10:18], uint64(qos.Deadline.Period))

	data[18] = byte(qos.Liveliness.Kind)
	binary.BigEndian.PutUint64(data[19:27], uint64(qos.Liveliness.LeaseDuration))

	data[27] = byte(qos.History.Kind)
	binary.BigEndian.PutUint32(data[28:32], uint32(qos.History.Depth))

	return data
}

// QoS策略反序列化
func DeserializeQoS(data []byte) (*QoSProfile, error) {
	if len(data) < 32 {
		return nil, fmt.Errorf("invalid QoS data length")
	}

	qos := &QoSProfile{
		Reliability: ReliabilityQosPolicy{
			Kind:            ReliabilityKind(data[0]),
			MaxBlockingTime: time.Duration(binary.BigEndian.Uint64(data[1:9])),
		},
		Durability: DurabilityQosPolicy{
			Kind: DurabilityKind(data[9]),
		},
		Deadline: DeadlineQosPolicy{
			Period: time.Duration(binary.BigEndian.Uint64(data[10:18])),
		},
		Liveliness: LivelinessQosPolicy{
			Kind:          LivelinessKind(data[18]),
			LeaseDuration: time.Duration(binary.BigEndian.Uint64(data[19:27])),
		},
		History: HistoryQosPolicy{
			Kind:  HistoryKind(data[27]),
			Depth: int(binary.BigEndian.Uint32(data[28:32])),
		},
	}

	if err := qos.Validate(); err != nil {
		return nil, err
	}

	return qos, nil
}
